<?php
//Lzphp框架核心
class Lzphp{
	
	protected $_config = array();

    public function __construct($config)
    {
        $this->_config = $config;				
    }
		
	 // 运行程序 run()方法则调用用类自身方法，完成：自动加载类文件、监测开发环境、过滤敏感字符、移除全局变量的老用法、和处理路由。
    public function run()
	{
		 spl_autoload_register(array($this, 'loadClass'));
		 $this->removeMagicQuotes();
		 $this->unregisterGlobals();
		 $this->setDbConfig();
		 $this->route();//路由截取 获取url地址 ，截取出控制器 方法 和传值的参数
	}
	
	  // 删除敏感字符
    public function addslashes_deep($value)
    {
    	 if (empty($value))
    	{
        	return $value;
    	}
     	else
    	{
        	return is_array($value) ? array_map(array($this, 'addslashes_deep'), $value)  : addslashes($value);
    	} 
    }

    // 检测敏感字符并删除
    public function removeMagicQuotes()
    {
    	if(!get_magic_quotes_gpc())
		{
			$_GET = isset($_GET) ? $this->addslashes_deep($_GET ) : '';
            $_POST = isset($_POST) ? $this->addslashes_deep($_POST ) : '';
            $_COOKIE = isset($_COOKIE) ? $this->addslashes_deep($_COOKIE) : '';
            $_SESSION = isset($_SESSION) ? $this->addslashes_deep($_SESSION) : '';	
		}
    }
	
	 // 检测自定义全局变量并移除。因为 register_globals 已经弃用，如果
    // 已经弃用的 register_globals 指令被设置为 on，那么局部变量也将
    // 在脚本的全局作用域中可用。 例如， $_POST['foo'] 也将以 $foo 的
    // 形式存在，这样写是不好的实现，会影响代码中的其他变量。 相关信息，
    // 参考: http://php.net/manual/zh/faq.using.php#faq.register-globals
    public function unregisterGlobals()
    {
        if (ini_get('register_globals')) {
            $array = array('_SESSION', '_POST', '_GET', '_COOKIE', '_REQUEST', '_SERVER', '_ENV', '_FILES');
            foreach ($array as $value) {
                foreach ($GLOBALS[$value] as $key => $var) {
                    if ($var === $GLOBALS[$key]) {
                        unset($GLOBALS[$key]);
                    }
                }
            }
        }
    }
	
	 // 配置数据库信息
    public function setDbConfig()
    {
        if ($this->_config['db']) {
            Model::$dbConfig = $this->_config['db'];
        }
    }
	
	public function route()
	{
		$controllerName = $this->_config['defaultController'];
        $actionName = $this->_config['defaultAction'];
        $param = array();
		
		$url = $_SERVER['REQUEST_URI'];
	 	// 清除?之后的内容
        $position = strpos($url, '?');
        $url = $position === false ? $url : substr($url, 0, $position);
        // 删除前后的“/”
        $url = trim($url, '/');
		if ($url) {
            // 使用“/”分割字符串，并保存在数组中
            $urlArray = explode('/', $url);
            // 删除空的数组元素
            $urlArray = array_filter($urlArray);
            // 获取控制器名
            $controllerName = ucfirst($urlArray[0]);           
            // 获取动作名
            array_shift($urlArray); //移除数组第一个元素
            $actionName = $urlArray ? $urlArray[0] : $actionName;            
            // 获取URL参数
            array_shift($urlArray);
            $param = $urlArray ? $urlArray : array();
        }
		// 判断控制器和操作是否存在
        $controller = $controllerName . 'Controller';
        if (!class_exists($controller)) {
            exit($controller . '控制器不存在');
        }
        if (!method_exists($controller, $actionName)) {
            exit($actionName . '方法不存在');
        }
		
		// 如果控制器和操作名存在，则实例化控制器，因为控制器对象里面
        // 还会用到控制器名和操作名，所以实例化的时候把他们俩的名称也
        // 传进去。结合Controller基类一起看
        $dispatch = new $controller($controllerName, $actionName);
        // $dispatch保存控制器实例化后的对象，我们就可以调用它的方法，
        // 也可以像方法中传入参数，以下等同于：$dispatch->$actionName($param)
        call_user_func_array(array($dispatch, $actionName), $param);
		
	}
	
	
	 // 自动加载控制器和模型类 
    public static function loadClass($class)
	{
		//引入核心类
		$frame_class = __DIR__.'/'.$class.".class.php";
		$controllers = APP_PATH . 'application/controllers/' . $class . '.php';
		$models = APP_PATH . 'application/models/' . $class . '.php';
		
		if(file_exists($frame_class))
		{
			include $frame_class;
		}
				
		if (file_exists($controllers))
		{
			// 加载应用控制器类
            include $controllers;
		}
		if(file_exists($models))
		{
			// 加载应用Model类
			include $models;
		}
		
		
	}
}
